

#ifndef __CE_OBJECT_H__
#define __CE_OBJECT_H__

/**
 * \addtogroup engine
 * @{
 */

#define CE_OBJECT																				\
private:																								\
	int _refCount;																				\
public:																									\
	void AddRef () { ++_refCount; }												\
	void Release () {	--_refCount; 												\
	if (_refCount <= 0) delete this; }										\
	int GetRefCount () const { return _refCount; }				\
private:

#define CE_OBJECT_CONSTR _refCount = 1;

#define CE_UNSET(dst) if ((dst)) (dst)->Release (); (dst) = 0
#define CE_SET(dst, src) if ((src)) (src)->AddRef (); if ((dst)) (dst)->Release (); dst = src

/**
 * @brief Refcountable object
 */
struct iObject
{
	virtual ~iObject () { }

	virtual void AddRef () = 0;

	virtual void Release () = 0;

	virtual int GetRefCount () const  = 0;

};


template<typename T>
class ceRef
{
private:
  T*  _ref;

public:
  ceRef (T* t)
    : _ref(t)
  {
  }

  ~ceRef ()
  {
	}

  T* operator* ()
  {
    return _ref;
  }


  T* operator-> ()
  {
    return _ref;
  }


	operator T* ()  {
		return _ref;
	}


};

template<typename T>
class cePtr
{
private:
  T*  _ptr;

public:
  cePtr (T* t)
    : _ptr(t)
  {
  }

  ~cePtr ()
  {
  }

  T* operator* ()
  {
    return _ptr;
  }

  const T* operator* () const
  {
    return _ptr;
  }

  T* operator-> ()
  {
    return _ptr;
  }



	operator T* ()  {
		return _ptr;
	}



};


template<typename T>
class ceReleasePtr
{
private:
  T*  _ptr;

public:
  ceReleasePtr (T* t)
    : _ptr(t)
  {
  }

  template<typename O>
  ceReleasePtr (O& o)
    : _ptr((T*)o)
  {
  }

	~ceReleasePtr ()
	{
		if (_ptr)
			{
				_ptr->Release ();
			}
	}

	
  T* operator* ()
  {
    return _ptr;
  }

  const T* operator* () const
  {
    return _ptr;
  }

  T* operator-> ()
  {
    return _ptr;
  }

  const T* operator-> () const
  {
    return _ptr;
  }
	

	operator T* ()  {
		return _ptr;
	}

	operator const T* () const {
		return _ptr;
	}

  template<typename O>
  ceReleasePtr<T> operator= (O& o)
  {
    if (_ptr)
      {
        _ptr->Release ();
      }
    _ptr = (T*)o;
    return *this;
  }

};

/** @} */

#endif /* !__CE_OBJECT_H__ */
